/**
 * 
 */
package com.feizhi.common.search;

import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.QueryBuilder;
import org.apache.lucene.util.Version;
import org.lionsoul.jcseg.analyzer.JcsegAnalyzer4X;
import org.lionsoul.jcseg.core.JcsegTaskConfig;

/**
 * @author shuaqiu
 */
public class HelloLucene {
    
    public static void main(String[] args) {
        // 0. Specify the analyzer for tokenizing text.
        // The same analyzer should be used for indexing and searching
        Analyzer analyzer = new JcsegAnalyzer4X(JcsegTaskConfig.COMPLEX_MODE);

        // 1. create the index
        Directory index = new RAMDirectory();

        try {
            createIndex(analyzer, index);

            // 2. query
            // 新词 ， 也就是 那些 在 字典 中都 没有 收录 过 ， 但 又 确实 能 称为 词 的 那些 词 。 最 典型的 是 人名 ， 人 可以 很容易 理解 句子 “ 王军虎 去 广州 了 ” 中 ， “ 王军虎 ” 是个 词 ， 因为 是 一个人 的 名字 ， 但 要是 让 计算机 去 识别 就 困难 了 。 如果 把 “ 王军虎 ” 做为 一个 词 收录 到 字典 中去 ， 全世界 有 那么 多 名字 ， 而且 每时每刻 都有 新增 的 人名 ， 收录 这些 人名 本身 就是 一项 巨大 的 工程 。 即使 这 项 工作 可以 完成 ， 还是 会 存在 问题 ， 例如 ： 在 句子 “ 王军 虎头虎脑 的 ” 中 ， “ 王军虎 ” 还能 不能 算 词 ？ 
            String querystr = "典型*";
            
            query(analyzer, index, querystr);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void createIndex(Analyzer analyzer, Directory directory) throws IOException {
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
    
        IndexWriter w = new IndexWriter(directory, config);
        addDoc(w, "Lucene in Action", "193398817");
        addDoc(w, "Lucene for Dummies", "55320055Z");
        addDoc(w, "Managing Gigabytes", "55063554A");
        addDoc(w, "The Art of Computer Science", "9900333X");
        addDoc(w, "新词，也就是那些在字典中都没有收录过，但又确实能称为词的那些词。最典型的是人名，人可以很容易理解句子“王军虎去广州了”中，“王军虎”是个词，因为是一个人的名字，但要是让计算机去识别就困难了。如果把“王军虎”做为一个词收录到字典中去，全世界有那么多名字，而且每时每刻都有新增的人名，收录这些人名本身就是一项巨大的工程。即使这项工作可以完成，还是会存在问题，例如：在句子“王军虎头虎脑的”中，“王军虎”还能不能算词？", "9900333X");
        w.close();
    }

    private static void addDoc(IndexWriter writer, String title, String isbn) throws IOException {
        Document doc = new Document();
        doc.add(new TextField("title", title, Field.Store.YES));
    
        // use a string field for isbn because we don't want it tokenized
        doc.add(new StringField("isbn", isbn, Field.Store.YES));
        writer.addDocument(doc);
    }

    private static void query(Analyzer analyzer, Directory directory, String querystr) throws IOException {
        // the "title" arg specifies the default field to use
        // when no field is explicitly specified in the query.
        // Query q = new QueryParser(Version.LUCENE_40, "title", analyzer).parse(querystr);
        Query q = new QueryBuilder(analyzer).createPhraseQuery("title", querystr);

        // 3. search
        int hitsPerPage = 10;
        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);
        TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
        searcher.search(q, collector);
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        // 4. display results
        System.out.println("Found " + hits.length + " hits.");
        for (int i = 0; i < hits.length; ++i) {
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);
            System.out.println((i + 1) + ". " + d.get("isbn") + "\t" + d.get("title"));
        }

        // reader can only be closed when there
        // is no need to access the documents any more.
        reader.close();
    }
}
